/**
A3_1
Lukas Bayard
5044154

The following program draws a series of particle spouts in the shape of a flower.


*/


#include "A3_1.h"
#include "GumdropSkeleton.h"
#include "Floor.h"
#include "Particles.h"


/*************************************************************************************************************/
/*
/* Sample Assignment 0 Extended: Use of Euler angles and polar coordinates. 
/*	Dated : May 13th 2004						Author: Ramgopal R,
												r_rajago@cs.concordia.ca
/*												Computer Graphics and Visualization Lab, Concordia University
/*************************************************************************************************************/

const float PI = 3.14159265;

static GLdouble cameraLocation [3];		// For keeping track of where the camera is located.
static GLdouble cameraLookAt [3];		// Keeps track of what the camera points at
static GLdouble cameraHeight [3];		// tracks the camera's height

/** Unclear about Polar coordinates for the camera */
double theta_camera;					// Polar Coordinates for the camera
double phi_camera;
double rad_camera;
/* ********************************************/



GLfloat fovy = 100.0;						// For perspective projections  - field of view y
GLint height;
GLint width;


//Add a GumdropSkeleton
GumdropSkeleton myGdS;

//Rotate Model
GLfloat modelAngle = 0.0;

// Main entry point of the program
void  main (int argc, char** argv)
{
	help();
	glutInit (&argc, argv);											// Initalize GLUT
	glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);		// Set display mode.
	glutInitWindowPosition (50, 100);								// Set top-left display window position
	glutInitWindowSize (800, 600);									// Set display-window width and height
	glutCreateWindow ("Project Gumdrop");										// Create display window
	initialize ();													//Execute initialize procedure
	glutDisplayFunc(display);										//Register the displat function to be displayed
	glutReshapeFunc(reshapeWindow);	

	
	glutKeyboardFunc(keyPress);										//Check if any keys are pressed
	glutSpecialFunc(specialKeyPress);

	glutTimerFunc(15, idle, 0);

	glutMainLoop ( );												//Display everything and wait


}



void help() {
	cout <<
		"Project: Fluid.\n\n"
        "Made by: Lukas Bayard  #5044154\n"
		"         Ho Cuong Tram #5229952\n"
		"\n"
        "Keys have the following effect:\n"
		"  PAGE_UP   to set the licking fluid.\n"
        "  a  to move the gumdrop to the left.\n"
        "  d  to move the gumdrop to the right.\n"
        "  s  to move the gumdrop to the forward.\n"
        "\n"
        "  UP/DOWN ARROW     key  rotate up/down.\n"
        "  LEFT/RIGHT ARROW  key  rotate left/right.\n"
		<< endl;
}



/** initalize: Sets display window parameters */
void initialize (void)
{
/*************************************************************************************************************/
/*
/* Sample Assignment 0 Extended: Use of Euler angles and polar coordinates. 
/*	Dated : May 13th 2004						Author: Ramgopal R,
												r_rajago@cs.concordia.ca
/*												Computer Graphics and Visualization Lab, Concordia University
/*************************************************************************************************************/
	/** Initialize global camera variables */
	cameraLocation [0] = 0.0;				//For use in the 'eye' parameter for the gluLookAt(..). Also the initial camera position. 
	cameraLocation [1] = 25.0;
	cameraLocation [2] = 0.0;

	cameraLookAt [0] = 0.0;					//For use in the 'center' parameter for the gluLookAt(..). Also the inital orientation.
	cameraLookAt [1] = 0.0;
	cameraLookAt [2] = 0.0;

	cameraHeight [0] = 0.0;					//For use in the 'up' paraemeter for the gluLookAt(..). Also the up direction of the camera.
	cameraHeight [1] = 1.0;
	cameraHeight [2] = 0.0;
	/***********************************/
	/** Polar coordinates for the camera */
	phi_camera = 90.0 * (PI/180);
	theta_camera = 115.0;
	rad_camera = sqrt(cameraLocation[0] * cameraLocation[0] + cameraLocation[1] * cameraLocation[1] + cameraLocation[2] * cameraLocation[2]);
	/*************************************/

/* *********************************************************************************************************************/


	//randomize the program
	srand (time (0));

	myGdS.LoadGumdropSkeleton();
	InitializeParticle();
	glMatrixMode (GL_PROJECTION);			//Set projection parameters
	glLoadIdentity ();						//Load identity values
	gluPerspective (fovy, 
		(GLfloat)width/(GLfloat)height,
		1.0, 100.0);

	glMatrixMode (GL_MODELVIEW);			// Change the current matrix mode to Model-view matrix.

	glLoadIdentity ();
	
	glClearColor (0.0, 0.0, 0.0, 0.0);		//Set the display-window to black
	glEnable (GL_DEPTH_TEST);				//What is this for?
						
}



void keyPress (unsigned char key, int x, int y)
{/*************************************************************************************************************/
/*
/* Sample Assignment 0 Extended: Use of Euler angles and polar coordinates. 
/*	Dated : May 13th 2004						Author: Ramgopal R,
												r_rajago@cs.concordia.ca
/*												Computer Graphics and Visualization Lab, Concordia University
/*************************************************************************************************************/
	switch (key)
	{
	case 'f':			//f: move the camera foward
		rad_camera -= 0.1;
		break;
	case 'b':			//b: move the camera backward
		rad_camera += 0.1;
		break;
	case 'w':			//w: move the gumdrop forward
		myGdS.PlayWalkingAnimation();
		break;
	case 'a':			//a: move the gumdrop left
		modelAngle -= 100.0 * (PI/180);
		break;
	case 'd':			//d: move the gumdrop Right
		modelAngle += 100.0 * (PI/180);
		break;
	case 27:			//ESC: Exit the prorgam
		exit(0);
	}


	glutPostRedisplay();
}



void specialKeyPress(int key, int x, int y)
{/*************************************************************************************************************/
/*
/* Sample Assignment 0 Extended: Use of Euler angles and polar coordinates. 
/*	Dated : May 13th 2004						Author: Ramgopal R,
												r_rajago@cs.concordia.ca
/*												Computer Graphics and Visualization Lab, Concordia University
/*************************************************************************************************************/
	switch (key)
	{
	case GLUT_KEY_LEFT:		//Rotate the camera in a counterclockwise direction about the y-axis 
		theta_camera -= 1.0 * (PI/180);
		break;
	case GLUT_KEY_RIGHT:	//Rotate the camera in a clockwise direction about the y-axis
		theta_camera += 1.0 * (PI/180);
		break;
	case GLUT_KEY_UP:		//Rotate the camera in a counterclockwise direction about the x-axis
		phi_camera -= 1.0 * (PI/180);
		break;
	case GLUT_KEY_DOWN:		//Rotate the camera in a clockwise direction about the x-axis
		phi_camera += 1.0 * (PI/180);
		break;
	}

	//Manipulate particle controls
	FunctionKeys(key, x, y);

	glutPostRedisplay();
}



// Draw the lines (x,y,z)
void axes ()
{
	// Draw the positive side of the lines x,y,z
	
	glPushMatrix();							
	glBegin(GL_LINES);
		glColor3f (0.0, 1.0, 0.0);			// Green for x axis
		glVertex3f(0,0,0);
		glVertex3f(10,0,0);
		glColor3f(1.0,0.0,0.0);				// Red for y axis
		glVertex3f(0,0,0);
		glVertex3f(0,10,0);
		glColor3f(0.0,0.0,1.0);				// Blue for z axis
		glVertex3f(0,0,0);	
		glVertex3f(0,0,10);
	glEnd();
	
	// Dotted lines for the negative sides of x,y,z
	glEnable(GL_LINE_STIPPLE);				// Enable line stipple to use a dotted pattern for the lines
	glLineStipple(1, 0x0101);				// Dotted stipple pattern for the lines
	glBegin(GL_LINES);				
		glColor3f (0.0, 1.0, 0.0);			// Green for x axis
		glVertex3f(-10,0,0);
		glVertex3f(0,0,0);
		glColor3f(1.0,0.0,0.0);				// Red for y axis
		glVertex3f(0,0,0);
		glVertex3f(0,-10,0);
		glColor3f(0.0,0.0,1.0);				// Blue for z axis
		glVertex3f(0,0,0);
		glVertex3f(0,0,-10);
	glEnd();

	glDisable(GL_LINE_STIPPLE);				// Disable the line stipple
	glPopMatrix();							// Don't forget to pop the Matrix
}



// This function is called whenever the window size is changed
void reshapeWindow (int h, int w)
{
	
	height = h;
	width = w;

	glMatrixMode (GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(fovy, (GLfloat)w/(GLfloat)h, 1.0, 100.0);
	glMatrixMode (GL_MODELVIEW);
	glutPostRedisplay( );
	
}

// This function displays to the screen
void display (void)
{/*************************************************************************************************************/
/*
/* Sample Assignment 0 Extended: Use of Euler angles and polar coordinates. 
/*	Dated : May 13th 2004						Author: Ramgopal R,
												r_rajago@cs.concordia.ca
/*												Computer Graphics and Visualization Lab, Concordia University
/*************************************************************************************************************/
	glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glColor3f (1.0, 1.0, 1.0);

	glMatrixMode (GL_MODELVIEW);
	glLoadIdentity();

	
	cameraLocation[1] = rad_camera * cos (phi_camera);
	cameraLocation[2] = rad_camera * sin (phi_camera) * cos (theta_camera);
	cameraLocation[0] = rad_camera * sin (phi_camera) * sin (theta_camera); //Set the camera position as captured by the polar coordinates

	gluLookAt (cameraLocation[0], cameraLocation[1], cameraLocation[2],cameraLookAt[0], cameraLookAt[1], cameraLookAt[2], 
			cameraHeight[0], cameraHeight[1], cameraHeight[2]);
/******************************************************************************/

			
	glPushMatrix();
		axes();
	glPopMatrix();

	glPushMatrix();
		DrawFloor(5);
	glPopMatrix();
	GLfloat n = GetConeWaterLevel();
	n = GetConeTopRadius();
	myGdS.SetConeWaterLevel(GetConeWaterLevel());
	myGdS.SetConeTopRadius(GetConeTopRadius());
	
	glPushMatrix();
		glRotatef(modelAngle, 0.0f, 1.0f, 0.0f);

		myGdS.DrawGumdropSkeleton();
	glPopMatrix();

	glPushMatrix();
		glRotatef(modelAngle, 0.0f, 1.0f, 0.0);
		glTranslatef(2.0f, -myGdS.GetRootBoneY(), -3.0f);
		glRotatef(-90, 0.0f, 1.0f, 0.0);
		glTranslatef(myGdS.GetRootBoneX(), -myGdS.GetRootBoneY(), -myGdS.GetRootBoneZ());
		DisplayParticles();		
	glPopMatrix();

	glutSwapBuffers();	
	glutPostRedisplay();
}

void idle(int value)
{
	glutTimerFunc(15, idle,0);

	EvolveParticle();
}

